#include <stdio.h>
#include <unistd.h>
#include "AsyncLib.h"

using namespace AL;

void FakeHttpGet(const char *lpUrl, const char *lpHeaders, std::function<void(const char *, int)>&& fnCallback)
{
	PostDelayedTask(1000, [fnCallback = std::move(fnCallback)]
	{
		fnCallback("Sample", 6);
	});
}

Task<std::string> FakeHttpGetAsync(const char *lpUrl, const char *lpHeaders)
{
	return WrapFnAsAsync<std::string>(FakeHttpGet, lpUrl, lpHeaders);
}

Task<> TestWrapFnAsAsync()
{
	FakeHttpGet("http://", nullptr, [](const char *lpData, int nSize)
	{
		printf("HttpGet: %d\n", nSize);
	});

	std::string strBody = co_await FakeHttpGetAsync("http://", nullptr);
	printf("HttpGetAsync: %s\n", strBody.c_str());

	co_await TaskWhenAll(DelayAsync(1000), DelayAsync(2000));
	size_t nIndex = co_await TaskWhenAny(DelayAsync(1000), DelayAsync(2000));
	assert(nIndex == 0);
	printf("index=%d\n", nIndex);
}

Task<int> MainAsync()
{
	co_await SwitchToThreadPool();
	printf("in threadpool\n");

	int res1 = co_await PostTask([]
	{
		sleep(1);
		return 12;
	});

	printf("res1=%d\n", res1);

	int res2 = co_await PostTask([]() -> Task<int>
	{
		co_await DelayAsync(1000);
		co_return 34;
	});

	printf("res2=%d\n", res2);

	PostDelayedTask(1000, []
	{
		printf("delayed task\n");
	});

	PostTask([]
	{
		printf("exception1\n");
		throw std::runtime_error("exception1");
	}).Forget();

	auto task = PostTask([]
	{
		printf("exception2\n");
		throw std::runtime_error("exception2");
	});

	try
	{
		co_await task;
	}
	catch (const std::runtime_error& e)
	{
		printf("runtime_error: %s\n", e.what());
	}

	co_await TestWrapFnAsAsync();
	co_return 0;
}

int main()
{
	AsyncLibInit();

	auto task = MainAsync();
	int result = task.Wait() ? task.Result() : 0;

	AsyncLibExit();
	return result;
}
